home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Tool Chest / Testing & Debugging / Virtual User / Virtual User Current Release / Examples / Example External Tools / ProcessTool / ProcessServices.cp < prev    next >
Encoding:
Text File  |  1998-06-04  |  17.9 KB  |  566 lines  |  [TEXT/MPS ]

  1. #ifndef        __ProcessServices__
  2. #include        "ProcessServices.h"
  3. #endif        __ProcessServices__
  4.  
  5. #include    <Processes.h>        // for all Process Mgr related stuff
  6. #include    <GestaltEqu.h>        // for Gestalt call & check
  7. #include    <ToolUtils.h>        // for HiWord & LoWord calls
  8. #include    <String.h>            // for strcmp
  9. #include    <StdLib.h>            // for atol conversion string to num
  10. #include    <SysEqu.h>            // for ROMBase
  11.  
  12. //—————————————————————————————————————————————————————————————————————————————————————
  13. //    ProcessServices::ProcessServices    -    constructor.
  14. //—————————————————————————————————————————————————————————————————————————————————————
  15. ProcessServices::ProcessServices( char* pSrvname ):Service( pSrvname )
  16. {
  17. }
  18.  
  19. //—————————————————————————————————————————————————————————————————————————————————————
  20. //    ProcessServices::CheckForProcessMgr    -    make sure it's available before calling it
  21. //—————————————————————————————————————————————————————————————————————————————————————
  22. OSErr
  23. ProcessServices::CheckForProcessMgr()
  24. {
  25.     OSErr        result;
  26.     long        response;
  27.     
  28.     result = Gestalt( gestaltOSAttr, &response );            // Get Process Mgr attributes.
  29.     if( result == noErr )
  30.     {
  31.         if( !(response & ( 1 << gestaltLaunchControl )))    // If proper attribute not set:
  32.         {
  33.             result = noProcessMgrErr;    // change result from noErr to noProcessMgrErr.
  34.         }
  35.     }
  36.     return result;                        // Returns noErr if Process Mgr is available.
  37. }
  38.  
  39.  
  40. //—————————————————————————————————————————————————————————————————————————————————————
  41. //    ProcessServices::ProcessName2cstr    -    Convert Pascal str (with nulls!) to C str
  42. //    (Desk accessory process names are Pascal strings that begin with a null: bad for C)
  43. //—————————————————————————————————————————————————————————————————————————————————————
  44. void
  45. ProcessServices::ProcessName2cstr( char* pProcessName )
  46. {
  47.     short        origLength;
  48.     char*        source;
  49.     char*        dest;
  50.     short        i;
  51.     char        theChar;
  52.     
  53.     origLength = pProcessName[0];
  54.     source = &pProcessName[1];                // (Pascal string text starts at index 1)
  55.     dest = pProcessName;                    // (C string text starts at index 0)
  56.     for( i = 1; i <= origLength; i++ )        // Index through each char of Pascal string:
  57.     {
  58.         theChar = *source++;                // Copy it only if it's non-null.
  59.         if( theChar )
  60.         {
  61.             *dest++ = theChar;
  62.         }
  63.     }
  64.     *dest = '\0';                            // Terminate the C string with a zero.
  65. }
  66.  
  67.  
  68. //—————————————————————————————————————————————————————————————————————————————————————
  69. //    ProcessServices::GetNamedProcessInfo    -    get information about given named app
  70. //—————————————————————————————————————————————————————————————————————————————————————
  71. OSErr
  72. ProcessServices::GetNamedProcessInfo( char* pDesiredProcessName, ProcessInfoRec* pInfoPtr )
  73. {
  74.     ProcessSerialNumber        thePSN;
  75.     char                    aProcessName[32];
  76.     
  77.     pInfoPtr->processInfoLength = sizeof( ProcessInfoRec );    // Set up for GetProcessInfo call
  78.     pInfoPtr->processName = ( StringPtr )aProcessName;
  79.     pInfoPtr->processAppSpec = nil;
  80.     
  81.     thePSN.highLongOfPSN = 0;
  82.     thePSN.lowLongOfPSN = kNoProcess;
  83.     while( GetNextProcess( &thePSN ) == noErr )                // Iterate through processes:
  84.     {
  85.         if( GetProcessInformation( &thePSN, pInfoPtr ) == noErr )
  86.         {
  87.             ProcessName2cstr( aProcessName );    // (Convert pascal string with possible nulls)
  88.             if( strcmp( aProcessName, pDesiredProcessName ) == 0 )        // if name matches:
  89.             {
  90.                 return noErr;    // info rec now contains info for named app.
  91.             }
  92.         }
  93.     }
  94.     return noSuchProcessErr;    // No info rec with matching name found.
  95. }
  96.  
  97.  
  98. //—————————————————————————————————————————————————————————————————————————————————————
  99. //    ProcessServices::ExtractAddr    -    Get long address from given parameter
  100. //  (parameter can be a quoted longnumber 'number' or a regular Virtual User number )
  101. //—————————————————————————————————————————————————————————————————————————————————————
  102. OSErr
  103. ProcessServices::ExtractAddr(ScriptValue* pAddrItem, unsigned long* pAddrPtr)
  104. {
  105.     ValueKind        kind;            // The kind of parameter passed
  106.     char*            numString;        // If a string
  107.     
  108.     // Get what kind of parameter is passed in.
  109.     kind = pAddrItem->GetValueKind();
  110.     
  111.     // If a number: just get it and return it.
  112.     if( kind == kVUNumberKind )
  113.     {
  114.         *pAddrPtr = (( VUNumber* )pAddrItem)->GetNumber();
  115.         return noErr;
  116.     }
  117.     
  118.     // If a quoted string: expecting a quoted long number.
  119.     if( kind == kVUStringKind )
  120.     {
  121.         // Get the string.
  122.         numString = (( VUString* )pAddrItem )->GetText();
  123.         // Convert the string to a returned long number.
  124.         *pAddrPtr = atol( numString );
  125.         return noErr;
  126.     }
  127.     
  128.     // Else not a string or a list: return an error.
  129.     return extractAddrErr;
  130. }
  131.         
  132.         
  133. //—————————————————————————————————————————————————————————————————————————————————————
  134. //    ProcessServices::ValidateAddr    -    confirm address is RAM or ROM
  135. //—————————————————————————————————————————————————————————————————————————————————————
  136. OSErr
  137. ProcessServices::ValidateAddr( unsigned long pAddr )
  138. {
  139.     OSErr            result;
  140.     long            response;
  141.     unsigned long    ROMStart;
  142.     
  143.     // Check if address is in RAM:
  144.     result = Gestalt( gestaltVMAttr, &response );    // Get VM status in response.
  145.     if( result != noErr )
  146.     {
  147.         return result;
  148.     }
  149.  
  150.     if( response & ( 1 << gestaltVMPresent ))        // If VM active:
  151.     {
  152.         if( GetPageState(( void* )pAddr ) != kNotPaged )
  153.         {
  154.             return noErr;                            // Exit noErr if valid VM “RAM” address.
  155.         }
  156.     }
  157.     else                                            // Else VM not active:
  158.     {
  159.         result = Gestalt( gestaltPhysicalRAMSize, &response );    // Get RAM size in response.
  160.         if( result != noErr )
  161.         {
  162.             return result;
  163.         }
  164.         if( pAddr < ( unsigned long )response )
  165.         {
  166.             return noErr;                            // Exit noErr if within RAM size.
  167.         }
  168.     }
  169.     
  170.     // If not exited yet, address is not in RAM: check if address is in ROM:
  171.     ROMStart = *( unsigned long* )ROMBase;            // Get base address of ROM.
  172.     result = Gestalt( gestaltROMSize, &response );    // Get size of ROM in response.
  173.     if(result != noErr )
  174.     {
  175.         return result;
  176.     }
  177.     if( pAddr >= ROMStart && pAddr < ROMStart + ( unsigned long )response )
  178.     {
  179.         return noErr;                                // Exit noErr if with ROM boundaries.
  180.     }
  181.     else
  182.     {
  183.         return validateAddrErr;                        // Else return invalid address error.
  184.     }
  185. }
  186.  
  187.  
  188. //—————————————————————————————————————————————————————————————————————————————————————
  189. //—————————————————————————————————————————————————————————————————————————————————————
  190. //    ProcessNamesListService::ProcessNamesListService    -    constructor
  191. //—————————————————————————————————————————————————————————————————————————————————————
  192. ProcessNamesListService::ProcessNamesListService():ProcessServices( "ProcessNamesList" )
  193. {
  194. }
  195.  
  196. //—————————————————————————————————————————————————————————————————————————————————————
  197. //    ProcessNameListService::ProcessRequest    -    get list of process names
  198. //—————————————————————————————————————————————————————————————————————————————————————
  199. OSErr
  200. ProcessNamesListService::ProcessRequest( Request* pReq )
  201. {
  202.     OSErr                result;
  203.     VUList*                namesList;
  204.     ProcessInfoRec        info;
  205.     char                aProcessName[32];
  206.     ProcessSerialNumber    thePSN;
  207.  
  208.     result = CheckForProcessMgr();                        // Make sure Process Mgr is available.
  209.     if( result != noErr )
  210.     {
  211.         pReq->SetErrorCode( result );
  212.         pReq->SetErrorMessage( "ProcessTool: ProcessNamesList - Process Mgr not available on this Mac" );
  213.         return result;
  214.     }
  215.     
  216.     namesList = new VUList;                                // Make a list type for V.U.
  217.  
  218.     info.processInfoLength = sizeof( ProcessInfoRec );
  219.     info.processName = ( StringPtr )aProcessName;
  220.     info.processAppSpec = NULL;
  221.     
  222.     thePSN.highLongOfPSN = 0;
  223.     thePSN.lowLongOfPSN = kNoProcess;
  224.     while( GetNextProcess( &thePSN ) == noErr )            // Iterate through processes:
  225.     {
  226.         if( GetProcessInformation( &thePSN, &info ) == noErr )
  227.         {
  228.             ProcessName2cstr( aProcessName );            // Convert process name for V.U.
  229.             namesList->PutNthItem( aProcessName );        // Add process name to list
  230.             
  231.         }
  232.     }
  233.     pReq->SetReturnValue( namesList );                    // Return the list.
  234.     return noErr;
  235. }
  236.             
  237.  
  238. //—————————————————————————————————————————————————————————————————————————————————————
  239. //—————————————————————————————————————————————————————————————————————————————————————
  240. //    FrontProcessNameService::FrontProcessNameService    -    constructor
  241. //—————————————————————————————————————————————————————————————————————————————————————
  242. FrontProcessNameService::FrontProcessNameService():ProcessServices( "FrontProcessName" )
  243. {
  244. }
  245.  
  246. //—————————————————————————————————————————————————————————————————————————————————————
  247. //    FrontProcessNameService::ProcessRequest    -    get name of front process
  248. //—————————————————————————————————————————————————————————————————————————————————————
  249. OSErr
  250. FrontProcessNameService::ProcessRequest( Request* pReq )
  251. {
  252.     OSErr                result;
  253.     ProcessSerialNumber    thePSN;
  254.     ProcessInfoRec        info;
  255.     char                theProcessName[32];
  256.     
  257.     result = CheckForProcessMgr();                        // Make sure Process Mgr is available.
  258.     if( result != noErr )
  259.     {
  260.         pReq->SetErrorCode( result );
  261.         pReq->SetErrorMessage( "ProcessTool: FrontProcessNameList - Process Mgr not available on this Mac" );
  262.         return result;
  263.     }
  264.  
  265.     result = GetFrontProcess( &thePSN );                // Get info about front process
  266.     if( result != noErr )
  267.     {
  268.         pReq->SetErrorCode( result );
  269.         pReq->SetErrorMessage( "ProcessTool: FrontProcessName - unable to get front process" );
  270.         return result;
  271.     }
  272.     
  273.     info.processInfoLength = sizeof( ProcessInfoRec );
  274.     info.processName = ( StringPtr )&theProcessName;
  275.     info.processAppSpec = nil;
  276.     result = GetProcessInformation( &thePSN, &info );
  277.     if( result != noErr )
  278.     {
  279.         pReq->SetErrorCode( result );
  280.         pReq->SetErrorMessage( "ProcessTool: FrontProcessName - unable to get process's name" );
  281.         return result;
  282.     }
  283.     ProcessName2cstr( theProcessName );                    // Convert process name for V.U.
  284.     pReq->SetReturnValue( theProcessName );                // Return process name.
  285.     return noErr;
  286. }
  287.  
  288.     
  289. //—————————————————————————————————————————————————————————————————————————————————————
  290. //—————————————————————————————————————————————————————————————————————————————————————
  291. //    PartitionSizeService::PartitionSizeService    -    constructor
  292. //—————————————————————————————————————————————————————————————————————————————————————
  293. PartitionSizeService::PartitionSizeService():ProcessServices( "PartitionSize" )
  294. {
  295. }
  296.  
  297. //—————————————————————————————————————————————————————————————————————————————————————
  298. //    PartitionSizeService::ProcessRequest    -    get partition size of front process
  299. //—————————————————————————————————————————————————————————————————————————————————————
  300. OSErr
  301. PartitionSizeService::ProcessRequest( Request* pReq )
  302. {
  303.     OSErr            result;
  304.     ValueKind        tItemKind;
  305.     ScriptValue*    tParam;
  306.     char*            theProcessName;
  307.     ProcessInfoRec    info;
  308.     
  309.     // Make sure Process Mgr is available.
  310.     result = CheckForProcessMgr();
  311.     if( result != noErr )
  312.     {
  313.         pReq->SetErrorCode( result );
  314.         pReq->SetErrorMessage( "ProcessTool: PartitionSize - Process Mgr not available on this Mac" );
  315.         return result;
  316.     }
  317.     
  318.     // Make sure there is 1 parameter
  319.     if( pReq->GetParamCount() != 1 )
  320.     {
  321.         pReq->SetErrorCode( paramErr );
  322.         pReq->SetErrorMessage( "ProcessTool: PartitionSize - wrong number of parameters" );
  323.         return paramErr;
  324.     }
  325.     
  326.     // Read the parameter, specifying it to be a string.
  327.     tItemKind = kVUStringKind;
  328.     result = pReq->GetNthParam( 1, tParam, tItemKind );
  329.     if( result != noErr )
  330.     {
  331.         pReq->SetErrorCode( result );
  332.         pReq->SetErrorMessage( "ProcessTool: PartitionSize - failed to get process name parameter" );
  333.         return result;
  334.     }
  335.     theProcessName = (( VUString* )tParam )->GetText();
  336.     
  337.     // Get the process information for that named application.
  338.     result = GetNamedProcessInfo( theProcessName, &info );
  339.     if( result != noErr )
  340.     {
  341.         pReq->SetErrorCode( result );
  342.         pReq->SetErrorMessage( "ProcessTool: PartitionSize - unable to get process info" );
  343.         return result;
  344.     }
  345.     
  346.     // Return the partitionsize value from the process information.
  347.     pReq->SetReturnValue(( long )info.processSize );
  348.     return noErr;
  349. }
  350.  
  351.  
  352. //—————————————————————————————————————————————————————————————————————————————————————
  353. //—————————————————————————————————————————————————————————————————————————————————————
  354. //    FreeMemService::FreeMemService    -    constructor
  355. //—————————————————————————————————————————————————————————————————————————————————————
  356. FreeMemService::FreeMemService():ProcessServices( "FreeMem" )
  357. {
  358. }
  359.  
  360. //—————————————————————————————————————————————————————————————————————————————————————
  361. //    FreeMemService::ProcessRequest    -    get free memory in front process's heap
  362. //—————————————————————————————————————————————————————————————————————————————————————
  363. OSErr
  364. FreeMemService::ProcessRequest( Request* pReq )
  365. {
  366.     OSErr            result;
  367.     ValueKind        tItemKind;
  368.     ScriptValue*    tParam;
  369.     char*            theProcessName;
  370.     ProcessInfoRec    info;
  371.     
  372.     // Make sure Process Mgr is available.
  373.     result = CheckForProcessMgr();
  374.     if( result != noErr )
  375.     {
  376.         pReq->SetErrorCode( result );
  377.         pReq->SetErrorMessage( "ProcessTool: FreeMem - Process Mgr not available on this Mac" );
  378.         return result;
  379.     }
  380.     
  381.     // Make sure there is 1 parameter
  382.     if( pReq->GetParamCount() != 1 )
  383.     {
  384.         pReq->SetErrorCode( paramErr );
  385.         pReq->SetErrorMessage( "ProcessTool: FreeMem - wrong number of parameters" );
  386.         return paramErr;
  387.     }
  388.     
  389.     // Read the parameter, specifying it to be a string.
  390.     tItemKind = kVUStringKind;
  391.     result = pReq->GetNthParam( 1, tParam, tItemKind );
  392.     if( result != noErr )
  393.     {
  394.         pReq->SetErrorCode( result );
  395.         pReq->SetErrorMessage( "ProcessTool: FreeMem - failed to get process name parameter" );
  396.         return result;
  397.     }
  398.     theProcessName = (( VUString* )tParam )->GetText();
  399.     
  400.     // Get the process information for that named application.
  401.     result = GetNamedProcessInfo( theProcessName, &info );
  402.     if( result != noErr )
  403.     {
  404.         pReq->SetErrorCode( result );
  405.         pReq->SetErrorMessage( "ProcessTool: FreeMem - unable to get process info" );
  406.         return result;
  407.     }
  408.     
  409.     // Return the free memory value from the process information.
  410.     pReq->SetReturnValue(( long )info.processFreeMem );
  411.     return noErr;
  412. }
  413.  
  414.  
  415.  
  416. //—————————————————————————————————————————————————————————————————————————————————————
  417. //    ReadByteService::ReadByteService    -    constructor
  418. //—————————————————————————————————————————————————————————————————————————————————————
  419. ReadByteService::ReadByteService():ProcessServices( "ReadByte" )
  420. {
  421. }
  422.  
  423. //—————————————————————————————————————————————————————————————————————————————————————
  424. //    ReadByteService::ProcessRequest    -    read a byte from RAM or ROM
  425. //—————————————————————————————————————————————————————————————————————————————————————
  426. OSErr
  427. ReadByteService::ProcessRequest( Request* pReq )
  428. {
  429.     ValueKind        tItemKind;
  430.     OSErr            result;
  431.     ScriptValue*    tParam;
  432.     unsigned long    addr;
  433.     short            byteValue;
  434.  
  435.     // Make sure there is just one parameter.
  436.     if( pReq->GetParamCount() != 1 )
  437.     {
  438.         pReq->SetErrorCode( paramErr );
  439.         pReq->SetErrorMessage( "ProcessTool: ReadByte - wrong number of parameters" );
  440.         return paramErr;
  441.     }
  442.     
  443.     // Read the parameter. (It can be a number or longnumstring, so allow anything at first.)
  444.     tItemKind = kVUAnyKind;
  445.     result = pReq->GetNthParam( 1, tParam, tItemKind );
  446.     if( result != noErr )
  447.     {
  448.         pReq->SetErrorCode( result );
  449.         pReq->SetErrorMessage( "ProcessTool: ReadByte - failed to get address parameter" );
  450.         return result;
  451.     }
  452.  
  453.     // Convert the parameter (either form) to a long address of where to read bytes.
  454.     result = ExtractAddr( tParam, &addr );
  455.     if( result != noErr )
  456.     {
  457.         pReq->SetErrorCode( result );
  458.         pReq->SetErrorMessage( "ProcessTool: ReadByte - bad address parameter" );
  459.         return result;
  460.     }
  461.     result = ValidateAddr( addr );
  462.     if( result != noErr )
  463.     {
  464.         pReq->SetErrorCode( result );
  465.         pReq->SetErrorMessage( "ProcessTool: ReadByte - specified address is not in RAM or ROM" );
  466.         return result;
  467.     }
  468.     byteValue = ( short )( *(( Byte* )addr ));
  469.     pReq->SetReturnValue( byteValue );
  470.     return noErr;
  471. }
  472.     
  473.     
  474. //—————————————————————————————————————————————————————————————————————————————————————
  475. //    ReadBlockService::ReadBlockService    -    constructor
  476. //—————————————————————————————————————————————————————————————————————————————————————
  477. ReadBlockService::ReadBlockService():ProcessServices( "ReadBlock" )
  478. {
  479. }
  480.  
  481. //—————————————————————————————————————————————————————————————————————————————————————
  482. //    ReadBlockService::ProcessRequest    -    read a block of bytes from RAM or ROM
  483. //—————————————————————————————————————————————————————————————————————————————————————
  484. OSErr
  485. ReadBlockService::ProcessRequest( Request* pReq )
  486. {
  487.     ValueKind        tItemKind;
  488.     OSErr            result;
  489.     ScriptValue*    tParam;
  490.     unsigned long    addr;
  491.     short            lengthCount;
  492.     VUList*            readBlockList;
  493.     short            i;
  494.  
  495.     // Make sure there are 2 parameters
  496.     if( pReq->GetParamCount() != 2 )
  497.     {
  498.         pReq->SetErrorCode( paramErr );
  499.         pReq->SetErrorMessage( "ProcessTool: ReadBlock - wrong number of parameters" );
  500.         return paramErr;
  501.     }
  502.     
  503.     // Read the 1st parameter. (Can be a number or longnumstring, so allow anything at first.)
  504.     tItemKind = kVUAnyKind;
  505.     result = pReq->GetNthParam( 1, tParam, tItemKind );
  506.     if( result != noErr )
  507.     {
  508.         pReq->SetErrorCode( result );
  509.         pReq->SetErrorMessage( "ProcessTool: ReadBlock - failed to get address parameter" );
  510.         return result;
  511.     }
  512.     
  513.     // Convert the parameter (either form) to a long address of where to read a byte.
  514.     result = ExtractAddr( tParam, &addr );
  515.     if( result != noErr )
  516.     {
  517.         pReq->SetErrorCode( result );
  518.         pReq->SetErrorMessage( "ProcessTool: ReadBlock - bad address parameter" );
  519.         return result;
  520.     }
  521.     
  522.     // Read the 2nd parameter, specifying it to be a number.
  523.     tItemKind = kVUNumberKind;
  524.     result = pReq->GetNthParam( 2, tParam, tItemKind );
  525.     if(result != noErr )
  526.     {
  527.         pReq->SetErrorCode( result );
  528.         pReq->SetErrorMessage( "ProcessTool: ReadBlock - failed to get count parameter" );
  529.         return result;
  530.     }
  531.     
  532.     // Get the number, the count of how many bytes to read back.
  533.     lengthCount = (( VUNumber* )tParam )->GetNumber();
  534.     
  535.     // Make sure the starting address is in RAM or ROM.
  536.     result = ValidateAddr( addr );
  537.     if( result != noErr )
  538.     {
  539.         pReq->SetErrorCode( result );
  540.         pReq->SetErrorMessage( "ProcessTool: ReadBlock - starting address is not in RAM or ROM" );
  541.         return result;
  542.     }
  543.     
  544.     // Make sure the ending address is in RAM or ROM.
  545.     result = ValidateAddr( addr + lengthCount - 1 );
  546.     if( result != noErr )
  547.     {
  548.         pReq->SetErrorCode( result );
  549.         pReq->SetErrorMessage( "ProcessTool: ReadBlock - ending address is not in RAM or ROM" );
  550.         return result;
  551.     }
  552.     
  553.     // All clear! Read bytes from memory & add to end of a list.
  554.     readBlockList = new VUList;
  555.     for( i = 0; i < lengthCount; i++ )
  556.     {
  557.         readBlockList->PutNthItem(( short )(*( Byte* )( addr + i )));
  558.     }
  559.     
  560.     // Return the list.
  561.     pReq->SetReturnValue( readBlockList );
  562.     return noErr;
  563. }
  564.  
  565.  
  566.